home *** CD-ROM | disk | FTP | other *** search
- #include "MPDialogs.h"
- #include "Utilities.h"
- #include "ListControl.h"
- #include <Palettes.h>
- #include <Icons.h>
-
- /********************************************************************************
- *
- * Main Multi-Pane Dialog Routines
- *
- ********************************************************************************/
-
- DialogPtr OpenMPDialog(short resID, DefActionUPP defAction, ClickActionUPP clickProc,
- EditActionUPP editAction, GroupActionUPP groupAction, Handle *theData)
- {
- DialogPtr dlog;
- GrafPtr oldPort;
- MPDHdl dataH;
- OSErr err = noErr;
- short i, num, *dPtr, iType;
- Str255 theStr;
- Handle iHandle, dHandle;
- Rect iRect;
- ListHandle theList;
- Cell theCell;
-
- // One-time initialization of utility routines
- if (!gInitMPDUtils) InitMPDUtils();
-
- // Open the MPD and allocate the MPD's MPDHdl
- if (!(dlog = MyGetCenteredDialog(resID, nil, nil, (WindowPtr) -1L))) {
- return NULL;
- }
- if (!(dataH = (MPDHdl) NewHandle(sizeof(MPDRec)))) {
- DisposeDialog(dlog);
- return NULL;
- }
- MoveHHi((Handle) dataH);
- SetWRefCon(dlog, (long) dataH);
- (*dataH)->radio = NULL;
- (*dataH)->currentPane = 1;
- // Set up Action Procedures as requested
- InstallAction(kItemAction, dlog, (UniversalProcPtr) clickProc);
- InstallAction(kEditAction, dlog, (UniversalProcPtr) editAction);
- InstallAction(kDefAction, dlog, (UniversalProcPtr) defAction);
- InstallAction(kGroupAction, dlog, (UniversalProcPtr) groupAction);
-
- // Run though the dialog items and set user items to be the gray box
- num = CountDITL(dlog);
- (*dataH)->baseItems = num + 1;
- for(i = kIconBox + 1; i <= num; i++) {
- GetDItem(dlog, i, &iType, &iHandle, &iRect);
- if ((iType & 0x7f) == userItem)
- SetItemToGray(dlog, i);
- }
-
- // Get ready for drawing
- GetPort(&oldPort);
- SetPort(dlog);
-
- // Fetch the DTL# resource, die if we can't
- if (!(dHandle = GetResource(kDTL, resID))) goto die3;
-
- HLock(dHandle);
-
- // Read in the pane IDs
- dPtr = (short *) *dHandle;
- num = (*dataH)->numPanes = *dPtr++;
- (*dataH)->paneIDs = (short *) NewPtr(num * sizeof(short));
- for(i=0; i<num; i++) {
- (*dataH)->paneIDs[i] = *dPtr++;
- dPtr += (*(char *) dPtr + sizeof(short)) >> 1;
- }
- (*dataH)->IconHandles = (Handle *) NewPtr(num * sizeof(Handle));
-
- // Set up the icon list control
- GetDItem(dlog, kIconBox, &iType, &iHandle, &iRect);
- if (!(theList = CLNew(rListCtl, true, &iRect, 0, 1, 60, 64, rIconDef, dlog,
- clVScroll | clActive | clKeyPos | clDrawIt))) goto die1;
- (*theList)->selFlags |= lOnlyOne;
- (*dataH)->theList = theList;
- LAddRow(num, 0, theList);
-
- // Add the icons and label to the list
- theCell.h = 0;
- dPtr = ((short *) *dHandle) + 1;
- for (theCell.v = 0; theCell.v < num; theCell.v++) {
- dPtr++;
- Pstrcpy(theStr, (ConstStr255Param) dPtr);
- dPtr += (*(char *) dPtr + sizeof(short)) >> 1;
- GetIconSuite(&(*dataH)->IconHandles[theCell.v], (*dataH)->paneIDs[theCell.v], svAllAvailableData);
- LSetCell(&(*dataH)->IconHandles[theCell.v], sizeof(Handle), theCell, theList);
- LAddToCell(theStr+1, theStr[0], theCell, theList);
-
- CreateRadioGroups(dlog, theCell.v);
- }
- ReleaseResource(dHandle);
-
- // Allocate the MPD and temporary data handles
- if (!*theData) {
- (*dataH)->theData = MPDTemplateFromDITL(dataH);
- *theData = (*dataH)->theData;
- *(long *) **theData = (*dataH)->currentPane;
- } else {
- (*dataH)->theData = *theData;
- (*dataH)->currentPane = *(long *) **theData;
- }
- (*dataH)->tmpData = NewHandle(GetHandleSize((*dataH)->theData));
- if (!(*dataH)->theData || !(*dataH)->tmpData) goto die2;
-
- // Display the first pane
- InstallDITL(dlog, (*dataH)->currentPane);
- HandleMPDAction(dlog, kR2TAction, 0);
- HandleMPDAction(dlog, kT2PAction, (*dataH)->currentPane);
-
- if (theList) {
- LDoDraw(true, theList);
- SetPt(&theCell, 0, (*dataH)->currentPane - 1);
- LSetSelect(true, theCell, theList);
- }
- ShowWindow(dlog);
- SetPort(oldPort);
-
- return dlog;
-
- die1:
- DisposePtr((Ptr) (*dataH)->IconHandles);
- die2:
- DisposePtr((Ptr) (*dataH)->paneIDs);
- DisposeHandle(dHandle);
- die3:
- DisposeHandle((Handle) dataH);
- DisposDialog(dlog);
- return NULL;
- }
-
- void CloseMPDialog(DialogPtr *dlog)
- {
- MPDHdl dataH;
- short i;
- RadioGroupPtr next, group;
-
- dataH = (MPDHdl) GetWRefCon(*dlog);
- // Preserve last open pane
- *(long *) *(*dataH)->theData = (*dataH)->currentPane;
- // Dispose of the icon suites
- for(i = 0; i < (*dataH)->numPanes; i++)
- DisposeIconSuite((*dataH)->IconHandles[i], true);
- DisposePtr((Ptr) (*dataH)->IconHandles);
- // Dispose of the radio group storage
- for(group=(*dataH)->radio; group; group=next) {
- next = group->next;
- DisposePtr((Ptr) group);
- }
- // Dispose of everything else
- DisposePtr((Ptr) (*dataH)->paneIDs);
- DisposeHandle((*dataH)->tmpData);
- DisposeHandle((Handle) dataH);
- DisposeDialog(*dlog);
- // Tell caller we closed the MPD
- *dlog = NULL;
- }
-
- short DoMPDialogEvent(DialogPtr *dlog, EventRecord *theEvent)
- {
- short itemHit = 0, dblClick, part;
- DialogPtr dptr;
- GrafPtr oldPort;
- WindowPtr window, fwin = FrontWindow();
- MPDHdl dataH;
- Cell theCell;
-
- GetPort(&oldPort);
- SetPort(*dlog);
-
- if (!*dlog) return kNotHandled;
- dataH = (MPDHdl) GetWRefCon(*dlog);
-
- // Handle events only for this MPD
- switch (theEvent->what) {
- case 0:
- break;
- case mouseDown:
- part = FindWindow(theEvent->where, &window);
- if (window != *dlog) return kNotHandled;
- switch (part) {
- case inDrag:
- DragWindow(window, theEvent->where, &qd.screenBits.bounds);
- SetPort(oldPort);
- return kHandled;
- case inGoAway:
- if (TrackGoAway(window, theEvent->where)) {
- CloseMPDialog(dlog);
- return kHandled;
- }
- break;
- }
- if (CLClick(*dlog, theEvent, &dblClick)) itemHit = kIconBox;
- break;
- case keyDown:
- case autoKey:
- if (fwin != *dlog) return kNotHandled;
- switch (theEvent->message & charCodeMask) {
- case kLeftArrow:
- theEvent->message = kUpArrow;
- goto doit;
- case kRightArrow:
- theEvent->message = kDownArrow;
- goto doit;
- case '\t':
- // Don't allow TAB to change panes if multiple edit fileds are on the pane
- if (MultipleEditFields(*dlog)) break;
- theEvent->message = (theEvent->modifiers & shiftKey) ? kUpArrow : kDownArrow;
- case kUpArrow:
- case kDownArrow:
- doit:
- if (CLKey(*dlog, theEvent)) itemHit = kIconBox;
- break;
- }
- break;
- case updateEvt:
- case activateEvt:
- if ((WindowPtr) theEvent->message != *dlog) return kNotHandled;
- break;
- default:
- return kNotHandled;
- }
-
- // After handling non-dialog window events, try for the dialog events including
- // key equivalents for both the main dialog and the current pane.
- if (!itemHit && !keyAltFilter(*dlog, kKeyStrings, 0, theEvent, &itemHit) &&
- !keyAltFilter(*dlog, (*dataH)->baseItems, (*dataH)->baseItems-1, theEvent, &itemHit)) {
- if (!IsDialogEvent(theEvent)) {
- SetPort(oldPort);
- return kNotHandled;
- }
- if (!DialogSelect(theEvent,&dptr,&itemHit)) {
- SetPort(oldPort);
- if (theEvent->what == mouseDown) return kHandled;
- return kNotHandled; // Not for us
- } else if (!itemHit) {
- SetPort(oldPort);
- return kHandled; // For us, but not exciting
- } else { // Handle revert when EditText fields change
- Handle iHandle;
- short iType;
- Rect iRect;
-
- GetDItem(*dlog, itemHit, &iType, &iHandle, &iRect);
- if (iType == editText) {
- if (theEvent->what == keyDown && (theEvent->message & charCodeMask) >= ' ') {
- (*dataH)->paneDirty = true;
- AbleDItem(*dlog, kBRevert, true);
- }
- SetPort(oldPort);
- return kHandled;
- }
- }
- }
-
- // Did something interesting happen?
- switch (itemHit) {
- case 0:
- break;
- case kBOk:
- // Save the values of the controls and retain MPD changes
- // The dialog can't be Oked if a validation error is returned
- if (HandleMPDAction(*dlog, kP2TAction, (*dataH)->currentPane))
- HandleMPDAction(*dlog, kT2RAction, 0);
- else break;
- case kBCancel:
- // Close the dialog if Oked or Canceled
- CloseMPDialog(dlog);
- break;
- case kBRevert:
- // Restore previous settings
- HandleMPDAction(*dlog, kT2PAction, (*dataH)->currentPane);
- (*dataH)->paneDirty = false;
- AbleDItem(*dlog, kBRevert, false);
- break;
- case kBFactory:
- // Restore factory defaults
- SetFactoryDefault(*dlog, (*dataH)->currentPane);
- (*dataH)->paneDirty = true;
- AbleDItem(*dlog, kBRevert, true);
- break;
- case kIconBox:
- // Has the pane changed?
- if (!(*dataH)->theList) return kHandled;
- theCell.h = theCell.v = 0;
- if (LGetSelect(true, &theCell, (*dataH)->theList)) {
- theCell.v++;
- if (theCell.v != (*dataH)->currentPane) {
- if (!HandleMPDAction(*dlog, kP2TAction, (*dataH)->currentPane)) {
- // We can't change the pane now
- theCell.v--;
- LSetSelect(false, theCell, (*dataH)->theList);
- theCell.v = (*dataH)->currentPane - 1;
- LSetSelect(true, theCell, (*dataH)->theList);
- return kHandled;
- }
- // Change the pane
- (*dataH)->currentPane = theCell.v;
- InstallDITL(*dlog, theCell.v);
- HandleMPDAction(*dlog, kT2PAction, theCell.v);
- }
- }
- break;
- default:
- // A control was clicked
- CallClickActionProc((*dataH)->ClickAction, kClickAction, *dlog, (*dataH)->currentPane, itemHit);
- if (!(*dataH)->paneDirty) {
- (*dataH)->paneDirty = true;
- AbleDItem(*dlog, kBRevert, true);
- }
- break;
- }
-
- SetPort(oldPort);
- return kHandled;
- }
-
- Boolean MultipleEditFields(DialogPtr dlog)
- {
- MPDHdl dataH;
- short numItems, i, iType, numEdits = 0;
- Handle iHandle;
- Rect iRect;
-
- if (!dlog) return false;
- dataH = (MPDHdl) GetWRefCon(dlog);
- numItems = CountDITL(dlog);
-
- for(i=(*dataH)->baseItems; i<=numItems; i++) {
- GetDItem(dlog, i, &iType, &iHandle, &iRect);
- if (iType == editText) numEdits++;
- }
- return ((numEdits > 1) ? true : false);
- }
-
- // UniversalProcPtr stuff for default Action Procedures
- #if USESROUTINEDESCRIPTORS
- RoutineDescriptor gClickActionRoutine = BUILD_ROUTINE_DESCRIPTOR(kClickProcInfo, DefaultClickAction);
- RoutineDescriptor gEditActionRoutine = BUILD_ROUTINE_DESCRIPTOR(kEditProcInfo, DefaultEditAction);
- RoutineDescriptor gGroupActionRoutine = BUILD_ROUTINE_DESCRIPTOR(kGroupProcInfo, DefaultGroupAction);
- RoutineDescriptor gDefActionRoutine = BUILD_ROUTINE_DESCRIPTOR(kDefProcInfo, DefaultAction);
- ClickActionUPP gClickActionProc = &gClickActionRoutine;
- EditActionUPP gEditActionProc = &gEditActionRoutine;
- GroupActionUPP gGroupActionProc = &gGroupActionRoutine;
- DefActionUPP gDefActionProc = &gDefActionRoutine;
- #else
- ClickActionUPP gClickActionProc = (ClickActionUPP) DefaultClickAction;
- EditActionUPP gEditActionProc = (EditActionUPP) DefaultEditAction;
- GroupActionUPP gGroupActionProc = (GroupActionUPP) DefaultGroupAction;
- DefActionUPP gDefActionProc = (DefActionUPP) DefaultAction;
- #endif
-
- short InstallAction(short aType, DialogPtr dlog, UniversalProcPtr actionProc)
- {
- MPDHdl dataH;
-
- dataH = (MPDHdl) GetWRefCon(dlog);
- switch (aType) {
- case kItemAction:
- (*dataH)->ClickAction = actionProc ? (ClickActionUPP) actionProc : gClickActionProc;
- break;
- case kEditAction:
- (*dataH)->EditAction = actionProc ? (EditActionUPP) actionProc : gEditActionProc;
- break;
- case kGroupAction:
- (*dataH)->GroupAction = actionProc ? (GroupActionUPP) actionProc : gGroupActionProc;
- break;
- case kDefAction:
- (*dataH)->DefAction = actionProc ? (DefActionUPP) actionProc : gDefActionProc;
- break;
- default:
- return kNotHandled;
- }
- return kHandled;
- }
-
- short RemoveAction(short aType, DialogPtr dlog)
- {
- return InstallAction(aType, dlog, NULL);
- }
-
- /********************************************************************************
- *
- * Multi-Pane Dialog Data Access Routines
- *
- ********************************************************************************/
-
- short GetMPDItem(Handle theData, short pane, short item, Ptr ptr, short len)
- {
- Ptr hPtr;
- short i;
-
- if (!theData) return keNullData;
- hPtr = *theData + sizeof(long);
-
- // Find the correct pane…
- for(i=1; i<pane; i++) {
- hPtr += 4;
- if (*(long *) hPtr == 0L) return keBadPane;
- }
- hPtr = *theData + sizeof(long) + *(long *) hPtr;
-
- // Find the correct item…
- for(item--;item; item--) {
- hPtr += (*(short *) hPtr) + sizeof(short);
- if (!*(short *) hPtr) return keBadItem;
- }
-
- // Get the value
- if (len != *(short *) hPtr) return keWrongSize;
- BlockMove(hPtr+sizeof(short), ptr, *(short *) hPtr);
- return noErr;
- }
-
- short SetMPDItem(Handle theData, short pane, short item, Ptr ptr, short len)
- {
- Ptr hPtr;
- short i;
-
- if (!theData) return keNullData;
- HLock(theData);
- hPtr = *theData + sizeof(long);
-
- // Find the correct pane…
- for(i=1; i<pane; i++) {
- hPtr += 4;
- if (*(long *) hPtr == 0L) return keBadPane;
- }
- hPtr = *theData + sizeof(long) + *(long *) hPtr;
-
- // Find the correct item…
- for(item--;item; item--) {
- hPtr += (*(short *) hPtr) + sizeof(short);
- if (!*(short *) hPtr) return keBadItem;
- }
-
- // Set the value
- if (len != *(short *) hPtr) return keWrongSize;
- BlockMove(ptr, hPtr+sizeof(short), *(short *) hPtr);
- return noErr;
- }
-
- /********************************************************************************
- *
- * Internal Multi-Pane Dialog Routines
- *
- ********************************************************************************/
-
- void InstallDITL(DialogPtr dlog, short pane)
- {
- MPDHdl dataH;
- Handle theDITL, iHandle;
- short i, num, iType;
- Rect iRect;
-
- dataH = (MPDHdl) GetWRefCon(dlog);
- // Pane is now no longer dirty
- (*dataH)->paneDirty = false;
- AbleDItem(dlog, kBRevert, false);
-
- // Remove old pane
- i = CountDITL(dlog) - (*dataH)->baseItems + 1;
- ShortenDITL(dlog, i);
-
- // Install new one
- theDITL = GetResource('DITL', (*dataH)->paneIDs[pane-1]);
- if (!theDITL) return;
- AppendDITL(dlog, theDITL, overlayDITL);
- ReleaseResource(theDITL);
-
- // Set all user items to be the gray box
- num = CountDITL(dlog);
- for(i=(*dataH)->baseItems; i<=num; i++) {
- GetDItem(dlog, i, &iType, &iHandle, &iRect);
- if ((iType & 0x7f) == userItem)
- SetItemToGray(dlog, i);
- }
- }
-
- Handle MPDTemplateFromDITL(MPDHdl dataH)
- {
- short ditl, i, dcount, iType, pseudoItem;
- short num = (*dataH)->numPanes, *DITList = (*dataH)->paneIDs;
- Handle h, iHandle, theData;
- DialogPtr dptr;
- Rect wRect, iRect;
- long hSize, tSize;
- DialogRecord storage;
-
- hSize = sizeof(long) * (num + 1);
- theData = NewHandle(hSize);
- MoveHHi(theData);
- SetRect(&wRect, 0, 0, 50, 50);
-
- // Process all the panes…
- for(ditl=0; ditl<num; ditl++) {
- // Load the pane's DITL so we can run through it, without knowing it's structure.
- ((long *) *theData)[ditl] = hSize;
- h = GetResource('DITL', DITList[ditl]);
- DetachResource(h);
- if (!h) continue; // Oops!
- dptr = NewDialog(&storage, &wRect, "\p", false, dBoxProc, (WindowPtr) -1, false, 0, h);
- if (!dptr) continue; // Oops!
-
- // Process each item in the pane…
- dcount = CountDITL(dptr);
- pseudoItem = 1; // start with item 1
- for(i=1; i<=dcount; i++) {
- GetDItem(dptr, i, &iType, &iHandle, &iRect);
- switch(iType & 0x7f) {
- case 4: // Button
- case 5: // Check box
- case 7: // Control
- SetHandleSize(theData, hSize+4);
- if (MemError()) goto error;
- *(short *) ((*theData) + hSize) = sizeof(short);
- hSize += sizeof(short);
- HLock(theData);
- CallDefActionProc((*dataH)->DefAction ,(*theData) + hSize, sizeof(short),
- iType, ditl+1, pseudoItem);
- HUnlock(theData);
- hSize += sizeof(short);
- pseudoItem++;
- break;
- case 6: // Radio Button
- tSize = GetRadioMPDSize((*dataH)->radio, ditl+1, i);
- // If the Radio Button is not part of a radio group,
- // handle it as a check box
- if (tSize) {
- SetHandleSize(theData, hSize+sizeof(short)+tSize);
- if (MemError()) goto error;
- *(short *) ((*theData) + hSize) = tSize;
- hSize += sizeof(short);
- HLock(theData);
- CallDefActionProc((*dataH)->DefAction, (*theData) + hSize, sizeof(short),
- iType, ditl+1, pseudoItem);
- HUnlock(theData);
- hSize += tSize;
- pseudoItem++;
- }
- break;
- case editText: // TextEdit field
- tSize = CallEditActionProc((*dataH)->EditAction,
- kCalcAction, NULL, iHandle, ditl+1, pseudoItem);
- SetHandleSize(theData, hSize+sizeof(short)+tSize);
- if (MemError()) goto error;
- *(short *) ((*theData) + hSize) = tSize;
- hSize += sizeof(short);
- HLock(theData);
- CallEditActionProc((*dataH)->EditAction,
- kInitAction, (*theData) + hSize, iHandle, ditl+1, pseudoItem);
- HUnlock(theData);
- hSize += tSize;
- pseudoItem++;
- break;
- default:
- break;
- }
- }
-
- // When done with all the normal items, do the radio grouped items
- HLock(theData);
- tSize = DoGroupAction(kCalcAction, (WindowPtr) dataH, NULL, ditl+1, NULL);
- HUnlock(theData);
- if (tSize) {
- SetHandleSize(theData, hSize+tSize);
- if (MemError()) goto error;
- DoGroupAction(kInitAction, (WindowPtr) dataH, *theData+hSize, ditl+1, &pseudoItem);
- hSize += tSize;
- }
- SetHandleSize(theData, hSize+sizeof(short));
- if (MemError()) goto error;
- *(short *) &(*theData)[hSize] = 0;
- hSize += sizeof(short);
- CloseDialog(dptr);
- }
- ((long *) *theData)[ditl] = 0L;
- if (hSize != GetHandleSize(theData)) SysBeep(3);
- SetHandleSize(theData, hSize + sizeof(long));
- if (MemError()) goto error;
- BlockMove(*theData, *theData + sizeof(long), hSize);
- *(long *) *theData = 1;
- return MemError() ? NULL : theData;
-
- error:
- DisposeHandle(theData);
- if (dptr) CloseDialog(dptr);
- return NULL;
- }
-
- short CreateMPDRadioGroup(DialogPtr dlog, short pane, short *itemList, short itemNum)
- {
- MPDHdl dataH;
- RadioGroupPtr group;
-
- dataH = (MPDHdl) GetWRefCon(dlog);
- group = (RadioGroupPtr) NewPtr(sizeof(RadioGroup) + itemNum * sizeof(short));
- if (!group) return dsMemFullErr;
- BlockMove(itemList, &group->items, itemNum * sizeof(short));
- group->num = itemNum;
- group->pane = pane;
- group->next = (*dataH)->radio;
- (*dataH)->radio = group;
- return noErr;
- }
-
- void CreateRadioGroups(DialogPtr dlog, short pane)
- {
- MPDHdl dataH;
- Handle h;
- short g, numGroups, numItems;
- short *p = NULL;
-
- dataH = (MPDHdl) GetWRefCon(dlog);
-
- if (!(h = GetResource(kGROUP, (*dataH)->paneIDs[pane]))) return;
- MoveHHi(h);
- HLock(h);
- p = (short *) *h;
- numGroups = *p++;
-
- for(g=0; g<numGroups; g++) {
- numItems = *p++;
- CreateMPDRadioGroup(dlog, pane+1, p, numItems);
- p += numItems;
- }
-
- HUnlock(h);
- ReleaseResource(h);
- }
-
- void SetFactoryDefault(DialogPtr dlog, short pane)
- {
- short i, iType, tSize, hilited = false, val, pseudoItem = 1;
- Handle iHandle;
- Rect iRect;
- MPDHdl dataH;
- RadioGroupPtr radio;
- Ptr tmpPtr;
-
- dataH = (MPDHdl) GetWRefCon(dlog);
- HLock((*dataH)->theData);
- radio = (*dataH)->radio;
-
- for(i=(*dataH)->baseItems; i<=CountDITL(dlog); i++) {
- GetDItem(dlog, i, &iType, &iHandle, &iRect);
- switch(iType & 0x7f) {
- case 4: // Button
- case 5: // Check box
- case 7: // Control
- CallDefActionProc((*dataH)->DefAction, (Ptr) &val, sizeof(short), iType,
- pane, pseudoItem);
- SetCtlValue((ControlHandle) iHandle, val);
- pseudoItem++;
- break;
- case 6: // Radio Button
- if (tSize = GetRadioMPDSize(radio, pane, i - (*dataH)->baseItems + 1)) {
- CallDefActionProc((*dataH)->DefAction, (Ptr) &val, sizeof(short),
- iType, pane, pseudoItem);
- SetCtlValue((ControlHandle) iHandle, val);
- pseudoItem++;
- }
- break;
- case editText:
- // Allocate a temporart pointer to hold the factory value, get the
- // default value, and finally set the control.
- tSize = CallEditActionProc((*dataH)->EditAction,
- kCalcAction, NULL, iHandle, pane, pseudoItem);
- if (!(tmpPtr = NewPtr(tSize))) break;
- CallEditActionProc((*dataH)->EditAction,
- kInitAction, tmpPtr, iHandle, pane, pseudoItem);
- CallEditActionProc((*dataH)->EditAction,
- kT2PAction, tmpPtr, iHandle, pane, pseudoItem);
- DisposePtr(tmpPtr);
- // Hilite first EditText field in the dialog
- if (!hilited) {
- SelIText(dlog, i, 0, 32768);
- hilited = true;
- }
- pseudoItem++;
- break;
- default:
- break;
- }
- }
-
- // After handling the normal controls, handle the radio grouped controls
- tSize = DoGroupAction(kCalcAction, (WindowPtr) dataH, NULL, pane, NULL);
- if (tSize) {
- if (!(tmpPtr = NewPtr(tSize))) return;
- DoGroupAction(kInitAction, (WindowPtr) dataH, tmpPtr, pane, &val);
- DoGroupAction(kT2PAction, dlog, tmpPtr, pane, &pseudoItem);
- DisposePtr(tmpPtr);
- }
-
- HUnlock((*dataH)->theData);
- return;
- }
-
- void ToggleGroup(DialogPtr dlog, RadioGroupPtr group, short item)
- {
- MPDHdl dataH;
- short i;
-
- dataH = (MPDHdl) GetWRefCon(dlog);
- for(i=0; i<group->num; i++) {
- SetCheckOrRadioButton(dlog, group->items[i] + (*dataH)->baseItems - 1, group->items[i] == item);
- }
- }
-
- short GetRadioMPDSize(RadioGroupPtr radio, short pane, short item)
- {
- RadioGroupPtr group;
- short i, ret = sizeof(short);
-
- // If the control is a member of a radio group, return zero, else return sizeof(short).
- for(group=radio; group; group=group->next) {
- if (group->pane == pane)
- for(i=0; i<group->num; i++) {
- if (group->items[i] == item) ret = 0;
- }
- }
- return ret;
- }
-
- /********************************************************************************
- *
- * Internal Multi-Pane Dialog Action Procedures
- *
- ********************************************************************************/
-
- short HandleMPDAction(DialogPtr dlog, short message, short pane)
- {
- MPDHdl dataH;
- long hSize;
-
- dataH = (MPDHdl) GetWRefCon(dlog);
- hSize = GetHandleSize((*dataH)->theData);
- switch (message) {
- case kR2TAction: // Transfer real to temporary
- HLock((*dataH)->theData);
- HLock((*dataH)->tmpData);
- BlockMove(*(*dataH)->theData, *(*dataH)->tmpData, hSize);
- HUnlock((*dataH)->theData);
- HUnlock((*dataH)->tmpData);
- break;
- case kP2TAction: // Transfer controls to temporary
- return P2TMPDAction(dlog, pane);
- case kT2PAction: // Transfer temporary to controls
- return T2PMPDAction(dlog, pane);
- case kT2RAction: // Transfer temporary to real
- HLock((*dataH)->theData);
- HLock((*dataH)->tmpData);
- BlockMove(*(*dataH)->tmpData, *(*dataH)->theData, hSize);
- HUnlock((*dataH)->theData);
- HUnlock((*dataH)->tmpData);
- break;
- default:
- return kNotHandled;
- }
- return kHandled;
- }
-
- short P2TMPDAction(DialogPtr dlog, short pane)
- {
- short i, iType, tSize, pseudoItem = 1, sSize;
- Handle iHandle;
- Rect iRect;
- MPDHdl dataH;
- Ptr hPtr;
- RadioGroupPtr radio;
-
- dataH = (MPDHdl) GetWRefCon(dlog);
- HLock((*dataH)->theData);
- hPtr = *(*dataH)->tmpData + sizeof(long) + ((long *) *(*dataH)->tmpData)[pane];
- radio = (*dataH)->radio;
-
- // Validate the pane, returning false if it doesn't
- for(i=(*dataH)->baseItems; i<=CountDITL(dlog); i++) {
- GetDItem(dlog, i, &iType, &iHandle, &iRect);
- // Abort transfer if something's gone awry…
- if (CallClickActionProc((*dataH)->ClickAction, kValidateAction, dlog, pane, i))
- return false;
- }
-
- // Store the control values into memory
- for(i=(*dataH)->baseItems; i<=CountDITL(dlog); i++) {
- GetDItem(dlog, i, &iType, &iHandle, &iRect);
-
- switch(iType & 0x7f) {
- case 4: // Button
- case 5: // Check box
- case 7: // Control
- sSize = *(short *) hPtr;
- hPtr += sizeof(short);
- *(short *) hPtr = GetCtlValue((ControlHandle) iHandle);
- hPtr += sSize;
- pseudoItem++;
- break;
- case 6: // Radio Button
- if (tSize = GetRadioMPDSize(radio, pane, i - (*dataH)->baseItems + 1)) {
- sSize = *(short *) hPtr;
- hPtr += sizeof(short);
- *(short *) hPtr = GetCtlValue((ControlHandle) iHandle);
- hPtr += sSize;
- pseudoItem++;
- }
- break;
- case editText:
- sSize = *(short *) hPtr;
- hPtr += sizeof(short);
- hPtr += CallEditActionProc((*dataH)->EditAction,
- kP2TAction, hPtr, iHandle, pane, pseudoItem);
- hPtr += sSize;
- pseudoItem++;
- break;
- default:
- break;
- }
- }
- hPtr += DoGroupAction(kP2TAction, dlog, hPtr, pane, &pseudoItem);
- HUnlock((*dataH)->theData);
- return true;
- }
-
- short T2PMPDAction(DialogPtr dlog, short pane)
- {
- short i, iType, tSize, hilited = false, pseudoItem = 1, sSize;
- Handle iHandle;
- Rect iRect;
- MPDHdl dataH;
- Ptr hPtr;
- RadioGroupPtr radio;
-
- dataH = (MPDHdl) GetWRefCon(dlog);
- HLock((*dataH)->theData);
- hPtr = *(*dataH)->tmpData + sizeof(long) + ((long *) *(*dataH)->tmpData)[pane];
- radio = (*dataH)->radio;
-
- // Set the controls based on the values in memory
- for(i=(*dataH)->baseItems; i<=CountDITL(dlog); i++) {
- GetDItem(dlog, i, &iType, &iHandle, &iRect);
- switch(iType & 0x7f) {
- case 4: // Button
- case 5: // Check box
- case 7: // Control
- sSize = *(short *) hPtr;
- hPtr += sizeof(short);
- SetCtlValue((ControlHandle) iHandle, *(short *) hPtr);
- hPtr += sSize;
- pseudoItem++;
- break;
- case 6: // Radio Button
- if (tSize = GetRadioMPDSize(radio, pane, i - (*dataH)->baseItems + 1)) {
- sSize = *(short *) hPtr;
- hPtr += sizeof(short);
- SetCtlValue((ControlHandle) iHandle, *(short *) hPtr);
- hPtr += sSize;
- pseudoItem++;
- }
- break;
- case editText:
- sSize = *(short *) hPtr;
- hPtr += sizeof(short);
- hPtr += CallEditActionProc((*dataH)->EditAction,
- kT2PAction, hPtr, iHandle, pane, pseudoItem);
- if (!hilited) {
- SelIText(dlog, i, 0, 32768);
- hilited = true;
- }
- hPtr += sSize;
- pseudoItem++;
- break;
- default:
- break;
- }
- CallClickActionProc((*dataH)->ClickAction, kInitAction, dlog, pane, i);
- }
- hPtr += DoGroupAction(kT2PAction, dlog, hPtr, pane, &pseudoItem);
- HUnlock((*dataH)->theData);
- return true;
- }
-
- short HandleRadioGroup(DialogPtr dlog, short item)
- {
- MPDHdl dataH;
- RadioGroupPtr group;
- short i, pane;
- short ret = kNotHandled;
-
- dataH = (MPDHdl) GetWRefCon(dlog);
- pane = (*dataH)->currentPane;
-
- // Return kHandled if the control was in a radio group,
- // otherwise return kNotHandled
- for(group=(*dataH)->radio; group; group=group->next) {
- if (group->pane != pane) continue;
- for(i=0; i<group->num; i++) {
- // We allow a radio control to be a member of more than one group.
- if (group->items[i] == item) {
- ret = kHandled;
- ToggleGroup(dlog, group, item);
- }
- }
- }
- return ret;
- }
-
- short DoGroupAction(short mType, DialogPtr dlog, Ptr hPtr, short pane, short *item)
- {
- short ret = 0, val;
- MPDHdl dataH;
- RadioGroupPtr group;
-
- switch (mType) {
- case kP2TAction:
- dataH = (MPDHdl) GetWRefCon(dlog);
- break;
- case kT2PAction:
- dataH = (MPDHdl) GetWRefCon(dlog);
- break;
- case kCalcAction:
- case kInitAction:
- dataH = (MPDHdl) dlog;
- dlog = NULL;
- break;
- default:
- return kNotHandled;
- }
-
- for(group=(*dataH)->radio; group; group=group->next) {
- if (group->pane == pane) {
- val = CallGroupActionProc((*dataH)->GroupAction,
- mType, group, (Handle) dataH, dlog, hPtr, pane, *item);
- if (item) {
- (*item)++;
- hPtr += val;
- }
- ret += val;
- }
- }
- return ret;
- }
-
- /********************************************************************************
- *
- * Default Action Procedures
- *
- ********************************************************************************/
-
- void DefaultAction(Ptr theData, short len, short iType, short pane, short item)
- {
- switch (iType & 0x7f) {
- case 4: // Button
- case 5: // Check Box
- case 6: // Radio Button
- case 7: // Control
- if (len == sizeof(short)) *(short *) theData = 0;
- break;
- }
- }
-
- short DefaultEditAction(short mType, Ptr hPtr, Handle iHandle, short pane, short item)
- {
- short ret = 0;
- Str255 textStr;
-
- switch (mType) {
- case kP2TAction:
- GetIText(iHandle, textStr);
- Pstrcpy((unsigned char *) hPtr, textStr);
- ret = 256;
- break;
- case kT2PAction:
- Pstrcpy(textStr, (unsigned char *) hPtr);
- SetIText(iHandle, textStr);
- ret = 256;
- break;
- case kCalcAction:
- ret = 256;
- break;
- case kInitAction:
- *hPtr = 0;
- break;
- default:
- break;
- }
- return ret;
- }
-
- short DefaultClickAction(short mType, DialogPtr dlog, short pane, short item)
- {
- MPDHdl dataH;
- short iType;
- Rect iRect;
- Handle iHandle;
-
- switch (mType) {
- case kValidateAction: // No default validation
- case kInitAction: // No default initialization actions
- return noErr;
- }
- // mType == kClickAction
-
- dataH = (MPDHdl) GetWRefCon(dlog);
- GetDItem(dlog, item, &iType, &iHandle, &iRect);
- switch(iType & 0x7f) {
- case 4: // Button
- // No default action for buttons
- break;
- case 5: // Check
- ToggleCheck(dlog, item);
- break;
- case 6: // Radio
- if (!HandleRadioGroup(dlog, item - (*dataH)->baseItems + 1))
- ToggleCheck(dlog, item);
- break;
- case 7: // CTRL
- // They handle themselves.
- break;
- }
- return noErr;
- }
-
- short DefaultGroupAction(short mType, RadioGroupPtr group, Handle H, DialogPtr dlog,
- Ptr hPtr, short pane, short item)
- {
- short i, value, ret = 0;
- MPDHdl dataH = (MPDHdl) H;
-
- switch (mType) {
- case kP2TAction:
- hPtr += sizeof(short);
- for(i=0; i<group->num; i++) {
- if (GetCheckOrRadio(dlog, group->items[i] + (*dataH)->baseItems - 1))
- *(short *) hPtr = i + 1;
- }
- ret += sizeof(short) + sizeof(short);
- break;
- case kT2PAction:
- hPtr += sizeof(short);
- for(i=0; i<group->num; i++) {
- if (value = (*(short *) hPtr) == i + 1)
- SetCheckOrRadioButton(dlog, group->items[i] + (*dataH)->baseItems - 1, value);
- else SetCheckOrRadioButton(dlog, group->items[i] + (*dataH)->baseItems - 1, 0);
- }
- ret += sizeof(short) + sizeof(short);
- break;
- case kCalcAction:
- ret += sizeof(short) + sizeof(short);
- break;
- case kInitAction:
- *(short *) hPtr = sizeof(short);
- hPtr += sizeof(short);
- *(short *) hPtr = 1;
- hPtr += sizeof(short);
- ret += sizeof(short) + sizeof(short);
- break;
- }
-
- return ret;
- }
-
-
- /********************************************************************************
- *
- * Utility Functions
- *
- ********************************************************************************/
-
-
- /* Custom dialog item which simply draws a gray box.
- * If run on a Mac without Color QuickDraw or in B&W mode, it draws a
- * stippled gray line, otherwise it draws a real gray line.
- */
- pascal void DrawGray (DialogPtr theDialog, short theItem)
- {
- Rect iRect;
- short iKind;
- Handle iHandle;
- RGBColor oBack, oFore, gFore;
- GrafPtr oldPort;
-
- GetPort(&oldPort);
- SetPort(theDialog);
- GetDItem (theDialog, theItem, &iKind, &iHandle, &iRect);
- if (gQDVersion && (*((CGrafPtr) qd.thePort)->portPixMap)->pixelSize > 1) {
- GetForeColor(&oFore);
- GetBackColor(&oBack);
- gFore = oFore;
- if (gQDVersion == 2 && GetGray(GetGDevice(), &oBack, &gFore)) {
- RGBForeColor(&gFore);
- } else {
- gFore.red = (oFore.red + oBack.red) / 2;
- gFore.green = (oFore.green + oBack.green) / 2;
- gFore.blue = (oFore.blue + oBack.blue) / 2;
- RGBForeColor(&gFore);
- }
- } else {
- PenPat(&qd.gray);
- }
-
- // Actuall draw the line. We really draw a box, so one could use this code
- // for doing other things.
- FrameRect(&iRect);
-
- // Put things back the way it was.
- if (gQDVersion && (*((CGrafPtr) qd.thePort)->portPixMap)->pixelSize > 1) {
- RGBForeColor(&oFore);
- RGBBackColor(&oBack);
- } else {
- PenPat(&qd.black);
- }
- SetPort(oldPort);
- }
-
- #if USESROUTINEDESCRIPTORS
- RoutineDescriptor gGrayRoutine = BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, DrawGray);
- UniversalProcPtr gGrayProc = &gGrayRoutine;
- #else
- UniversalProcPtr gGrayProc = (UniversalProcPtr) DrawGray;
- #endif
-
- /* Sets a dialog user item to be a gray box.
- * Uses UPPs for native PowerPC support.
- */
- void SetItemToGray(DialogPtr dlog, short item)
- {
- Handle iHandle;
- short iKind;
- Rect iRect;
-
- GetDItem (dlog, item, &iKind, &iHandle, &iRect);
- SetDItem(dlog, item, iKind, (Handle) gGrayProc, &iRect);
- }
-
- /* Hilite a dialog item.
- */
- void HiliteItem(DialogPtr dlgPtr, short itemNo, short state)
- {
- short iKind;
- Handle iHandle;
- Rect iRect;
-
- GetDItem(dlgPtr, itemNo, &iKind, &iHandle, &iRect);
- HiliteControl((ControlHandle) iHandle, state);
- }
-
- /* Enable or disable a menu item.
- */
- void AbleDisItem(short menu, short item, short flag)
- {
- MenuHandle theMenu = GetMHandle(menu);
-
- if (!theMenu) return;
-
- if (flag)
- EnableItem(theMenu, item);
- else
- DisableItem(theMenu, item);
- }
-
- /* Draw a Grow Icon in a window without those silly lines.
- */
- void MyDrawGrow(WindowPtr win)
- {
- RgnHandle curClip, rgn;
- Rect rct;
-
- if (rgn = NewRgn()) {
- rct = win->portRect;
- rct.left = rct.right - 15;
- rct.top = rct.bottom - 15;
- curClip = NewRgn();
- GetClip(curClip);
- RectRgn(rgn,&rct);
- SetClip(rgn);
- DrawGrowIcon(win);
- SetClip(curClip);
- DisposeRgn(curClip);
- DisposeRgn(rgn);
- }
- }
-
- /* Get the item handle for a dialog item.
- */
- ControlHandle GetItemHandle(DialogPtr theDialog, short item)
- {
- ControlHandle iHandle;
- Rect iRect;
- short iType;
-
- GetDItem(theDialog,item,&iType,(Handle *) &iHandle,&iRect);
- return iHandle;
- }
-
- /* Specialized version of KeyEquivFilter (in Uilities.c) to read the
- * key equivalent string from a different item number (theItem) and
- * to add an offset to the activated item, to allow DITL-local
- * item numbering in the key equivalent string.
- */
- pascal Boolean keyAltFilter(DialogPtr dlg, short theItem, short offset, EventRecord *event, short *item)
- {
- short itemType;
- Handle itemHndl;
- Rect itemRect;
- Str255 itemText;
- short i, theChr, theMod, equivChr, modMask, modVal, itemNum;
- long tick;
-
- if (event->what == updateEvt) {
- if (dlg == (DialogPtr)event->message) OutlineDialogItem(dlg, 1);
- return(false);
- }
-
- if (event->what != keyDown) return(false);
-
- itemNum = 0;
-
- theChr = event->message & charCodeMask;
- theMod = event->modifiers & keyCodeMask;
-
- if ((theChr == 0x0D) || (theChr == 0x03)) { /* If return or enter... */
- if (!(theMod & (cmdKey + optionKey + controlKey))) itemNum = 1;
- }
- else {
-
- GetDItem(dlg, theItem, &itemType, &itemHndl, &itemRect);
- GetIText(itemHndl, itemText);
-
- for (i = 1; i <= *itemText; i += 9) {
- equivChr = GetHexByte((char *)(itemText + i));
- modMask = GetHexByte((char *)(itemText + i + 2)) << 8;
- modVal = GetHexByte((char *)(itemText + i + 4)) << 8;
- itemNum = GetHexByte((char *)(itemText + i + 6));
- if (theChr == equivChr)
- if ((theMod & modMask) == modVal) break;
- itemNum = 0;
- }
- }
-
- if (itemNum) {
- itemNum += offset;
- GetDItem(dlg, itemNum, &itemType, &itemHndl, &itemRect);
- if ((* (ControlHandle) itemHndl)->contrlHilite == 255) return false;
- HiliteControl((ControlHandle)itemHndl, 1);
- tick = TickCount();
- while (TickCount() < tick + 10);
- HiliteControl((ControlHandle)itemHndl, 0);
- *item = itemNum;
- return(true);
- }
-
- return(false);
- }
-
- /* Return the value of a dialog item
- */
- short GetDItemValue(DialogPtr dlgPtr, short itemNo)
- {
- short iKind;
- Handle iHandle;
- Rect iRect;
-
- GetDItem(dlgPtr, itemNo, &iKind, &iHandle, &iRect);
- return(GetCtlValue((ControlHandle)iHandle));
- }
-
- /* Custom dialog centering routine which returns a color dialog port and
- * uses CenterWindow (Utilities.c) to actually center the window.
- */
- DialogPtr MyGetCenteredDialog(short id, DialogPtr storage, WindowPtr relatedWindow, WindowPtr behind)
- {
- DialogTHndl dlogResource;
- DialogPtr dialog;
- Handle ditl;
- Boolean oldVis;
- char hstate;
- OSErr err;
-
- dialog = nil;
- if (dlogResource = (DialogTHndl)GetAppResource('DLOG', id, &err)) {
- hstate = LockHandleHigh((Handle)dlogResource);
- oldVis = (*dlogResource)->visible;
- (*dlogResource)->visible = false;
- ditl = GetAppResource('DITL', id, &err);
- DetachResource(ditl);
- if (gQDVersion) {
- if (dialog =
- NewCDialog(storage, &(*dlogResource)->boundsRect,
- (*dlogResource)->title, false, (*dlogResource)->procID,
- behind, (*dlogResource)->goAwayFlag,
- (*dlogResource)->refCon, ditl)) {
- Rect sizeInfo = {0,0,0,0};
-
- CenterWindow(dialog, relatedWindow, sizeInfo);
- if (oldVis) ShowWindow(dialog);
- }
- } else {
- if (dialog =
- NewDialog(storage, &(*dlogResource)->boundsRect,
- (*dlogResource)->title, false, (*dlogResource)->procID,
- behind, (*dlogResource)->goAwayFlag,
- (*dlogResource)->refCon, ditl)) {
- Rect sizeInfo = {0,0,0,0};
-
- CenterWindow(dialog, relatedWindow, sizeInfo);
- if (oldVis) ShowWindow(dialog);
- }
- }
- (*dlogResource)->visible = oldVis;
- HSetState((Handle)dlogResource, hstate);
- }
- return(dialog);
- }
-
- /* Copy a Pascal string
- */
- void Pstrcpy(Str255 dest, ConstStr255Param src)
- {
- register short i;
-
- for(i=0; i <= src[0]; i++) {
- dest[i] = src[i];
- }
- }
-
- /* Enable or disable a dialog item
- */
- void AbleDItem(DialogPtr dlog, short item, short state)
- {
- Handle iHandle;
- Rect iRect;
- short iType;
-
- GetDItem(dlog, item, &iType, &iHandle, &iRect);
- HiliteControl((ControlHandle) iHandle, state ? 0 : 255);
- }
-